package com.joe.learn.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServerDemo {

    private static final Logger logger = LoggerFactory.getLogger(ServerDemo.class);

    public static void main(String[] args) {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //代码一：设置整个服务端执行所使用的线程池
            //TODO 问题：为什么要设置两个loopGroup。这两个在底层会有特别的用途吗？
            serverBootstrap.group(boss, worker)
                    //代码二：设置服务端使用的通道类型，作为服务端程序，必然选择ServerSocketChannel下面的各种实现类。
                    //如果是基于JDK的NIO的话，则是选择NioServerSocketChannel
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //代码三：该方法在客户端链接成功建立时被触发，方法入参就是新建立的客户端通道对象
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //代码四：获取socket通道的管道对象，并且向其中添加处理器
                            ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    ByteBuf delimiter = PooledByteBufAllocator.DEFAULT.buffer(2);
                                    delimiter.writeChar('\r');
                                    ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1000, false, delimiter));
                                    ByteBuf buf = (ByteBuf) msg;
                                    if (buf.readerIndex() != 0) {
                                        throw new IllegalStateException();
                                    }
                                    if (buf.writerIndex() != 16) {
                                        throw new IllegalStateException();
                                    }
                                    int a = buf.readInt();
                                    logger.info("buf:{}", a);
                                    buf.writeInt(a + 1);
                                    int b = buf.readInt();
                                    buf.writeInt(b + 2);
                                    logger.info("buf:{}", b);
                                    int c = buf.readInt();
                                    buf.writeInt(c + 3);
                                    logger.info("buf:{}", c);
                                    int d = buf.readInt();
                                    buf.writeInt(d + 4);
                                    logger.info("buf:{}", d);
                                    ctx.writeAndFlush(buf);
                                }

                                @Override
                                public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                                    //客户端关闭通道后，收到消息
                                    logger.info("客户端关闭通道");
                                }
                            });
                        }
                    });
            ChannelFuture sync = serverBootstrap.bind(2323).sync();
            sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

}
